home *** CD-ROM | disk | FTP | other *** search
- ;* BIOSIO.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Bios interface for I/O *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- ;* This module contains some "C" procedures wich save more register than*
- ;* C conventions need. It shouldn't be considered as an heresy since *
- ;* these procedures are fully conform to C rules; but it might *
- ;* significantly decrease the size of the object code since these *
- ;* procedures are called very often from assembly routines wich use *
- ;* all CPU registers *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL medium
- LOCALS @@
-
- INCLUDE "scheme.ash"
-
- RFILE EQU 03FH ; read from a file
- WFILE EQU 040H ; write to a file
- MOVPTR EQU 042H ; move file pointer
-
- CURSMASK EQU 01100000b ; cursor status bits
- NOCURSOR EQU 00100000b ; byte mask to disable cursor
-
- DATASEG
-
- curs_sav DW NOCURSOR*100h ; For saving the cursor size when it's
- mouse_use DW 0 ; are we using the mouse?
- curs_hide DW 1 ; non zero if text cursor should be hidden
-
- CODESEG
- ;************************************************************************
- ;* Generate a Bell Character *
- ;* *
- ;* Purpose: To generate a "bell character" (i.e., make a noise) to *
- ;* simulate the effect of outputting a bell character *
- ;* (control-G) in the output stream. *
- ;* *
- ;* Calling Sequence: zbell(); *
- ;* *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zbell USES es
- mov ax, 1760 ; sound a A6
- call sound C, ax
- xor ax, ax ; point to bios data segment
- mov es, ax
- mov cl, [BYTE es:046ch] ; timer tick counter (DWORD)
- inc cl
- inc cl
- @@loop:
- cmp [BYTE es:046ch], cl ; already 2 ticks away ?
- jnz @@loop
- call nosound C
- ret
- ENDP zbell
-
- ;************************************************************************
- ;* Open a File *
- ;* *
- ;* Calling sequence: stat = zopen(handle, pathname, access_code, length)*
- ;* where: int *handle - location to store handle *
- ;* returned by open request*
- ;* char *pathname - zero terminated string *
- ;* containing the file's *
- ;* pathname *
- ;* int access_code - 0=read, 1=write, *
- ;* 2=read and write *
- ;* int stat - the completion code *
- ;* 0=no errors *
- ;* 2=file not found *
- ;* 4=too many open files *
- ;* 5=access denied *
- ;* 12=invalid access *
- ;************************************************************************
- PROC C zopen USES si di, @@handle, @@pathname, @@mode, @@lengthptr
- mov ah, 03dh
- mov al, [BYTE @@mode] ; load access code
- mov dx, [@@pathname] ; load pointer to pathname
- int MSDOS
- jc @@return
- mov bx, [@@handle]
- mov [bx], ax ; Store returned handle value
-
- push ax
- mov bx, ax ; set bx to file handle
- xor cx, cx
- xor dx, dx
- mov ax, 4202h ; position file pointer at eof
- int MSDOS
- mov bx, [@@lengthptr]
- mov [WORD HIGH DWORD bx], dx; write DoubleWord length
- mov [WORD LOW DWORD bx], ax
-
- pop bx
- xor cx, cx
- xor dx, dx
- mov ax, 4200h ; reset file pointer to beg of file
- int MSDOS
- xor ax, ax ; set return code for normal return
- @@return:
- ret ; return
- ENDP zopen
-
- ;************************************************************************
- ;* Create a File *
- ;* *
- ;* Calling sequence: stat = zcreate(handle, pathname) *
- ;* where: int *handle - location to store handle *
- ;* returned by open request*
- ;* char *pathname - zero terminated string *
- ;* containing the file's *
- ;* pathname *
- ;* int stat - the completion code *
- ;* 0=no errors *
- ;* 3=path not found *
- ;* 4=too many open files *
- ;* 5=access denied *
- ;************************************************************************
- PROC C zcreate USES si di, @@handle, @@pathname
- mov ah, 03ch
- mov dx, [@@pathname] ; load pointer to pathname
- mov cx, 020h ; create with "archive" attribute
- int MSDOS
- jc @@return
- mov bx, [@@handle]
- mov [bx], ax ; Store returned handle value
- xor ax, ax
- @@return:
- ret
- ENDP zcreate
-
- ;************************************************************************
- ;* Close a File *
- ;* *
- ;* Calling sequence: stat = zclose(handle) *
- ;* where: int handle - handle returned by open *
- ;* request *
- ;* int stat - the completion code *
- ;* 0=no errors *
- ;* 6=invalid handle *
- ;************************************************************************
- PROC C zclose USES si di, @@handle
- mov ah, 03eh
- mov bx, [@@handle]
- int MSDOS ; issue close request
- jc @@return
- xor ax, ax ; set return code for normal return
- @@return:
- ret
- ENDP zclose
-
- ;************************************************************************
- ;* Read From a File *
- ;* *
- ;* Calling sequence: stat = zread(handle, buffer, length) *
- ;* where: int handle - handle returned by open *
- ;* request *
- ;* char *buffer - address of character *
- ;* buffer into which data *
- ;* is to be read *
- ;* int *length - on input, the maximum *
- ;* number of characters *
- ;* which the buffer will *
- ;* hold. On output, the *
- ;* number of characters *
- ;* actually read. Note: *
- ;* a return value of zero *
- ;* characters read *
- ;* indicates end of file. *
- ;* int stat - the completion code *
- ;* 0=no errors *
- ;* 5=access denied *
- ;* 6=invalid handle *
- ;************************************************************************
- PROC C zread USES si di, @@handle, @@buffer, @@lengthptr
- mov ah, 03fh
- mov dx, [@@buffer]
- mov bx, [@@lengthptr]
- mov cx, [bx] ; load length for read
- mov bx, [@@handle]
- int MSDOS
- jc @@return
- mov bx, [@@lengthptr]
- mov [bx], ax ; Store number of characters read
- xor ax, ax ; set return code for normal return
- @@return:
- ret
- ENDP zread
-
- ;************************************************************************
- ;* Write to a File *
- ;* *
- ;* Calling sequence: stat = zwrite(handle, buffer, length) *
- ;* where: int handle - handle returned by open *
- ;* char *buffer - address of character *
- ;* buffer from which data *
- ;* is to be written *
- ;* int *length - on input, the number of *
- ;* characters to write. *
- ;* The actual number of *
- ;* characters which were *
- ;* written is returned in *
- ;* "length" *
- ;* int stat - the completion code *
- ;* 0=no errors *
- ;* 5=access denied *
- ;* 6=invalid handle *
- ;************************************************************************
- PROC C zwrite USES si di, @@handle, @@buffer, @@lengthptr
- mov ah, 040h
- mov dx, [@@buffer]
- mov bx, [@@lengthptr]
- mov cx, [bx]
- mov bx, [@@handle]
- int MSDOS ; issue write request
- jc @@return
- mov bx, [@@lengthptr]
- mov [bx], ax ; Store number of characters written
- xor ax, ax ; set return code for normal return
- @@return:
- ret
- ENDP zwrite
-
- ;************************************************************************
- ;* Move the file pointer right before EOF character and overwrite it *
- ;* to fix the bug in open-extend-file *
- ;************************************************************************
- PROC C mov_fptr USES si di, @@handle:WORD
- LOCAL @@buffer:WORD
-
- mov al, 2 ; move the pointer to end of file
- mov dx, -128 ; and with offset (one record size)
- mov cx, -1
- mov ah, MOVPTR
- mov bx, [@@handle]
- int MSDOS
- jc @@return
- or dx, dx ; small file?
- jge @@bigfile
- xor ax, ax
- xor cx, cx
- xor dx, dx
- mov ah, MOVPTR
- int MSDOS
- jc @@return
- @@bigfile:
- lea dx, [@@buffer]
- @@loop:
- mov cx, 1 ; read one character at a time
- mov ah, RFILE ; read it
- int MSDOS
- jc @@return
- mov CL, [BYTE @@buffer]
- cmp CL, CTRL_Z ; reach eof character?
- je @@afterEOF
- or ax, ax ; at eof, but no eof char?
- je @@return
- jmp @@loop
-
- @@afterEOF:
- mov al, 1 ; move the pointer to the current
- mov dx, -1 ; location plus offset
- mov cx, -1
- mov ah, MOVPTR
- int MSDOS
- jc @@return
- mov cx, 1 ; file pointer points to EOF character
- mov bx, [@@handle]
- mov [@@buffer], 0
- lea dx, [@@buffer]
- mov ah, WFILE ; write one byte
- int MSDOS
- jc @@return
- mov al, 1 ; move the pointer to the current
- mov dx, -1 ; location plus offset
- mov cx, dx
- mov ah, MOVPTR
- mov bx, [@@handle] ; file handle
- int MSDOS
- jc @@return
- xor ax, ax
- @@return:
- ret
- ENDP mov_fptr
-
- ;************************************************************************
- ;* Read characters from a string *
- ;* *
- ;* Calling Sequence: stringrd(page, disp, buffer, &length) *
- ;* where page,disp: location of string-fed port *
- ;* buffer and length are as in ZREAD (see above) *
- ;* *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C stringrd USES si di ds es, @@page, @@disp, @@buffer, @@lengthptr
- mov bx, [@@lengthptr] ;cx=number of chars to transfer
- mov cx, [bx]
- mov di, [@@page] ;Get port page
- mov dx, di
- push ds
- ldpage ds, di
- mov di, [@@disp] ;ds:di point to port
- mov si, [(PORTDEF di).ptr.disp]
- mov bl, [(PORTDEF di).ptr.page]
- xor bh, bh
- ldpage ds, bx
- cmp [(ANYDEF si).tag], STRTYPE
- jne @@notstring
- sstrlen bx, si, OVERHEAD
- ldpage es, dx ;Restore ptr to port
- mov dx, [(PORTDEF es:di).chunk]
- sub bx, dx ;Set bx to # of chars left
- jns @@notpast
- xor bx, bx ;Set # of chars left to 0
- @@notpast:
- cmp bx, cx ;cx = min( # of chars left, maximum)
- jae @@maximum
- mov cx, bx
- @@maximum:
- add si, dx ;Adjust si into string
- add dx, cx
- mov [(PORTDEF es:di).chunk], dx
- mov di, [@@buffer]
- xor ax, ax
- mov dx, cx ;Remember string length
- pop es ;Uses C data segment
- cld
- rep movsb
- jmp @@storelen
-
- @@notstring:
- mov ax, -1 ;Ax nonzero signals error
- xor dx, dx
- pop es ;Uses C data segment
- @@storelen:
- mov bx, [@@lengthptr] ;Set LENGTH to # of chars read
- mov [WORD es:bx], dx
- ret
- ENDP stringrd
-
- ;************************************************************************
- ;* Clear a Window *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zclear USES si, @@row:word, @@col:word, @@nrows:word, @@ncols:word, @@attrib:word
- LOCAL @@vidmode
- lea si, [@@vidmode]
- mov [WORD si], -1
- mov ah, [BYTE LOW @@attrib]
- mov al, SPACE
- mov [@@attrib], ax
- @@loop:
- call zputc C, [@@row], [@@col], [@@attrib], [@@ncols], si
- inc [@@row]
- dec [@@nrows] ; decrement row count
- jnz @@loop
- ret
- ENDP zclear
-
- ;************************************************************************
- ;* Automatic Cursor Off/On *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zautohiding, @@newvalue:word
- mov ax, [@@newvalue]
- mov [curs_hide], ax
- ret
- ENDP zautohiding
-
- ;************************************************************************
- ;* Cursor Off/On internal signal for automatic hiding *
- ;* This feature can be enabled with the function zautohiding *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zcuroff USES si di ; !!! SAME AS NEXT PROCEDURE !!!
- cmp [mouse_use], 0
- je @@nomouse
- mov ax, 2 ; hide mouse
- int 33h
- @@nomouse:
- mov ah, 03 ; get the cursor position & mode
- xor bh, bh
- int IBM_CRT
- mov ah, ch
- and ah, CURSMASK ; cursor already cleared ?
- cmp ah, NOCURSOR
- je @@return
- or cx, cx ; this occur after CGA graph init...
- jz @@return
- mov [curs_sav], cx ; save it for restoration
- mov ch, NOCURSOR
- set_cursor:
- cmp [curs_hide], 0 ; when no hiding, skip BIOS call
- jz @@skip
- mov ah, 01h
- int IBM_CRT ; turn the cursor off
- @@skip:
- push es
- call is_graph_mode C ; need to plot off a cursor ?
- pop es
- or ax, ax
- jz @@return
- mov ax, 09dbh ; write a solid block
- mov cx, 1
- mov bx, 0ffh ; xor to current char
- int IBM_CRT
- cursor_ret:
- @@return:
- ret
- ENDP zcuroff
-
- PROC C zcuron USES si di ; !!! SAME AS PREVIOUS PROCEDURE !!!
- cmp [mouse_use], 0 ; is it off, or first use?
- je @@nomouse
- test [mouse_use], 2 ; disable first MouseOn()
- jnz @@regular
- or [mouse_use], 2 ; set regular flag
- jmp @@nomouse
- @@regular:
- mov ax, 1 ; show mouse
- int 33h
- @@nomouse:
- mov ah, 03 ; get the cursor position & mode
- xor bh, bh
- int IBM_CRT
- or cx, cx ; this occur after CGA graph init...
- jz @@restore
- mov ah, ch
- and ah, CURSMASK ; cursor already on ?
- cmp ah, NOCURSOR
- jne cursor_ret
- @@restore:
- mov cx, [curs_sav]
- jmp set_cursor ; branch to similar code
- ENDP zcuron
-
- ;************************************************************************
- ;* Put Cursor *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zputcur USES si di es, @@row:word, @@col:word
- mov dh, [BYTE @@row]
- mov dl, [BYTE @@col]
- xor bh, bh ; Page number
- mov ah, 02h ; load "put cursor" code
- int IBM_CRT
- ret
- ENDP zputcur
-
- ;************************************************************************
- ;* Scroll Window Up one line *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zscroll USES si, @@line, @@col, @@nline, @@ncols, @@attr
- LOCAL @@vidmode
- mov dh, [BYTE @@nline]
- dec dh ; if just one line, blank it only !
- jz @@blank
- mov dl, [BYTE @@ncols]
- dec dl
- mov ch, [BYTE @@line]
- mov cl, [BYTE @@col]
- mov ax, 0601h ; scroll window down one line
- xor bh, bh
- add dx, cx ; dx=Lower right corner
- push di
- int IBM_CRT
- pop di
- @@blank:
- lea si, [@@vidmode]
- mov [WORD si], -1
- mov bl, SPACE
- mov bh, [BYTE @@attr]
- mov cx, [WORD @@line]
- add cl, [BYTE @@nline]
- dec cl
- call zputc C, cx, [@@col], bx, [@@ncols], si
- jmp @@return
- @@return:
- ret
- ENDP zscroll
-
- ;************************************************************************
- ;* Scroll Window Down one line *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zscroll_d USES si, @@line, @@col, @@nline, @@ncols, @@attr
- LOCAL @@vidmode
- mov dh, [BYTE @@nline]
- dec dh ; if just one line, blank it only !
- jz @@blank
- mov dl, [BYTE @@ncols]
- dec dl
- mov ch, [BYTE @@line]
- mov cl, [BYTE @@col]
- mov ax, 0701h ; scroll window down one line
- xor bh, bh
- add dx, cx ; dx=Lower right corner
- push di
- int IBM_CRT
- pop di
- @@blank:
- lea si, [@@vidmode]
- mov [WORD si], -1
- mov bl, SPACE
- mov bh, [BYTE @@attr]
- call zputc C, [@@line], [@@col], bx, [@@ncols], si
- jmp @@return
- @@return:
- ret
- ENDP zscroll_d
-
- ;************************************************************************
- ;* Graphic/Text mode detection *
- ;* *
- ;* Returns 0 if display is currently in text mode *
- ;* 1 if display is currently in graphic mode *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C is_graph_mode USES es si di
- mov ax, 4dd4h ; detect HP 95 LX (with buggy bios)
- int 15h
- mov cx, bx
- mov ah, 0fh
- int 10h ; as a first shot, see what the BIOS thinks
- cmp al, 3
- jbe @@text
- cmp al, 7 ; these ones are for sure
- je @@text
- cmp cx, 'HP' ; on the '95,
- je @@graph ; if it ain't MONO, it's graphics
-
- call get_max_cols C ; calculate buffer size if each
- mov si, ax ; char would take 35 bits
- call get_max_rows C ; (= minimum graph 5 x 7 chars)
- inc ax
- mov dl, 5*7
- mul dl
- mul si ; dx:ax is number of bits used
- mov si, 8 ; convert to bytes
- div si
- mov dx, 40h ; Bios tables base address
- mov es, dx
- cmp [WORD es:4ch], ax ; compare real size with theoric size
- jb @@text
- @@graph:
- mov ax, 1
- jmp @@return
- @@text:
- xor ax, ax
- @@return:
- ret
- ENDP is_graph_mode
-
- ;************************************************************************
- ;* Output Character & Attribute To Window *
- ;* *
- ;* item: low byte contains character *
- ;* high byte contains attribute *
- ;* *
- ;* vidmode: Pointer to a free word for storing TEMPORARILY video mode. *
- ;* This should only be used to avoid testing it more than once *
- ;* during the same operation, but remember that the user is *
- ;* free to change whenever he wants the video mode and there *
- ;* should NOT be any global variable remembering video mode. *
- ;* This variable should contains -1 on first call *
- ;************************************************************************
- ;* By convention, low-level user-interface I/O routines (often used from*
- ;* assembly language) should preserve the Extra-Segment register (ES). *
- ;************************************************************************
- PROC C zputc USES ax bx cx dx si di, @@line, @@col, @@item, @@replicate, @@vidmode
- mov dh, [BYTE @@line] ; position the cursor
- mov dl, [BYTE @@col]
- xor bh, bh ; page zero
- mov ah, 02h
- int IBM_CRT
- mov bx, [@@vidmode] ; video mode known ?
- cmp [WORD bx], 0
- jge @@proceed
- call is_graph_mode C ; else detect it
- mov bx, [@@vidmode]
- mov [WORD bx], ax
- or ax, ax
- @@proceed:
- mov bx, [@@item] ; load char & attributes
- jz @@attribok
- push bx
- mov bl, bh
- mov cl, 4 ; use background color
- shr bl, cl
- push bx
- mov cx, [@@replicate]
- xor bh, bh
- mov al, 0dbh ; block character
- mov ah, 09h
- int IBM_CRT ; write the background (using blocks)
- pop ax
- pop bx
- cmp bl, SPACE ; just blanking ?
- je @@return
- and bh, 0fh ; prepare XOR shape of chars to write
- xor bh, al
- or bh, 80h
- @@attribok:
- mov ax, 0900h
- xchg al, bh ; page zero
- xchg al, bl ; char in al, attribute in bl
- mov cx, [@@replicate]
- int IBM_CRT
- @@return:
- ret
- ENDP zputc
-
- END